/*
 *  msw/windowImp.cpp
 *  mini
 *
 *  Created by jin on 1/1/11.
 *  Copyright 2011 cs. All rights reserved.
 *
 */
#include "msw/windowImp.h"

#include "window.h"
#include "mouseEvent.h"
#include "msw/graphic2D.h"
#include "tchar.h"

static HINSTANCE hInstance = NULL; // TODO : Store instance handle in our global variable
MSWWindowImp::WindowMap MSWWindowImp::s_map;

LRESULT CALLBACK MSWWindowImp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
        case WM_MOUSEMOVE:
        case WM_LBUTTONUP:
        case WM_LBUTTONDOWN:
        {
            WindowMap::iterator it = s_map.find(hWnd);
            if (it != s_map.end())
            {
                MouseEvent evt;
                evt.x = HIWORD(lParam);
                evt.y = LOWORD(lParam);
                evt.modify = 0;
                if (wParam & 0x4)
                    evt.modify |= SHIFT_DOWN;
                if (wParam & 0x8)
                    evt.modify |= CTRL_DOWN;

                switch (message)
                {
                    case WM_MOUSEMOVE:
                        it->second->OnMouseMove(evt);
                        break;
                    case WM_LBUTTONDOWN:
                        it->second->OnMouseDown(evt);
                        break;
                    case WM_LBUTTONUP:
                        it->second->OnMouseUp(evt);
                        break;
                }
            }
            break;
        }
        case WM_PAINT:
        case WM_DISPLAYCHANGE:
        {
            WindowMap::iterator it = s_map.find(hWnd);
            if (it != s_map.end())
            {
                hdc = BeginPaint(hWnd, &ps);
                it->second->OnPaint(MSWGraphic2D(hdc));
                EndPaint(hWnd, &ps);
            }

            break;
        }
        case WM_DESTROY:
        {
            WindowMap::iterator it = s_map.find(hWnd);
            if (it != s_map.end())
            {
                delete it->second;
            }
            PostQuitMessage(0);
            break;
        }
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

ATOM MSWWindowImp::RegisterWindowClass()
{
    static bool registered = false;
    if (registered)
        return 0;

    registered = true;

    WNDCLASSEX wcex;

    wcex.cbSize = sizeof (WNDCLASSEX);

    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = MSWWindowImp::WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = NULL;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
    wcex.lpszMenuName = _T("");
    wcex.lpszClassName = _T("MiniWindow");
    wcex.hIconSm = NULL;

    return RegisterClassEx(&wcex);
}

MSWWindowImp::MSWWindowImp(Window* owner_) : WindowImpBase(owner_)
{
    RegisterWindowClass();

    hwd = CreateWindow(_T("MiniWindow"), _T("hello"), WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

    if (hwd)
    {
        s_map[hwd] = owner;
    }
}

MSWWindowImp::~MSWWindowImp()
{
    WindowMap::iterator it = s_map.find(hwd);
    if (it != s_map.end())
    {
        s_map.erase(it);
    }
}

void* MSWWindowImp::GetHandle()
{
    return hwd;
}

void MSWWindowImp::Show(bool show)
{
    ShowWindow(hwd, show ? SW_SHOWNORMAL : SW_HIDE);
    UpdateWindow(hwd);
}